package Lib3d.MyUtils;


import Lib3d.Vector3d;

import java.awt.event.MouseEvent;

/**
 * A camera implementation.
 * 
 * @author Wassim Chegham
 * @version 0.1
 * @category Lib3d.MyUtils
 * 
 */
public class Camera {

    private static Vector3d cameraTrans = new Vector3d(0, 0, -800.0f);
    private static Vector3d cameraRot = new Vector3d(0, 0, 0);
    private static Vector3d cameraRotOld = new Vector3d(0, 0, 0);
    private static float delta = 0.0f;
    private static float angle = 0.0f;
    private static int xOrigin = (int) Camera.cameraTrans.get(0);

    public static float getRotatedX() {
        return Camera.cameraRot.get(0);
    }

    public static float getRotatedY() {
        return Camera.cameraRot.get(1);
    }

    public static float getRotatedZ() {
        return Camera.cameraRot.get(2);
    }

    public static float getTranslatedX() {
        return Camera.cameraTrans.get(0);
    }

    public static float getTranslatedY() {
        return Camera.cameraTrans.get(1);
    }

    public static float getTranslatedZ() {
        return Camera.cameraTrans.get(2);
    }

    public static void moveBackward(final float distance) {
        Camera.move(-distance);
    }

    public static void moveForward(final float distance) {
        Camera.move(distance);
    }

    public static void moveLeft(final float distance) {
        Camera.cameraTrans = new Vector3d(Camera.cameraTrans.get(0) + 10f,
                Camera.cameraTrans.get(1), Camera.cameraTrans.get(2));
    }

    public static void moveRight(final float distance) {
        Camera.cameraTrans = new Vector3d(Camera.cameraTrans.get(0) - 10f,
                Camera.cameraTrans.get(1), Camera.cameraTrans.get(2));
    }

    public static void setMouseMoveEvent(final MouseEvent e) {
        if (Camera.xOrigin >= 0) {
            // update deltaAngle
            Camera.delta = (e.getX() - Camera.xOrigin) * 0.001f;
            // update camera's direction
            Camera.cameraTrans = new Vector3d((float) Math.sin(Camera.angle
                    + Camera.delta), (float) -Math.cos(Camera.angle + Camera.delta),
                    Camera.cameraRot.get(2));
        }
    }

    public static void setMousePressedEvent(final MouseEvent e) {
        Camera.xOrigin = e.getX();
        Camera.cameraRotOld = new Vector3d(e.getY(), e.getX(), Camera.cameraRotOld.get(2));
    }

    public static void setMouseReleasedEvent(final MouseEvent e) {
        Camera.angle += Camera.delta;
        Camera.xOrigin = -1;
    }

    public static void setRotation(final MouseEvent e) {
        // please note that we inversed the X and Y axis for purpose.
        final float x = e.getX() - Camera.cameraRot.get(0);
        final float y = e.getY() - Camera.cameraRot.get(1);
        Camera.cameraRot = new Vector3d(Camera.cameraRot.get(1) + y,
                Camera.cameraRot.get(0) + x, Camera.cameraRot.get(2));
    }

    public static String showInfo() {
        return "Position[" + Camera.cameraTrans.toString() + "]\nRotation["
                + Camera.cameraRot.toString() + "]";
    }

    public static void turnLeft(final float angle) {
        final float x = Camera.cameraTrans.get(0)
                - (float) Math.sin(Camera.cameraRot.get(0));
        final float z = Camera.cameraTrans.get(2)
                - (float) Math.sin(Camera.cameraRot.get(2));
        Camera.cameraTrans = new Vector3d(x, Camera.cameraTrans.get(1), z);
        Camera.cameraRot = new Vector3d(Camera.cameraRot.get(0), Camera.cameraRot.get(1)
                - angle, Camera.cameraRot.get(2));
    }

    public static void turnRight(final float angle) {
        final float x = Camera.cameraTrans.get(0)
                + (float) Math.cos(Math.toRadians(Camera.cameraRot.get(0)));
        final float z = Camera.cameraTrans.get(2)
                - (float) Math.sin(Math.toRadians(Camera.cameraRot.get(2)));
        Camera.cameraTrans = new Vector3d(x, Camera.cameraTrans.get(1), z);
        Camera.cameraRot = new Vector3d(Camera.cameraRot.get(0), Camera.cameraRot.get(1)
                + angle, Camera.cameraRot.get(2));
    }

    public static void viewAxixX() {
        Camera.cameraRot = new Vector3d(0, 90, 0);
    }

    public static void viewAxixY() {
        Camera.cameraRot = new Vector3d(0, 0, 90);
    }

    public static void viewAxixZ() {
        Camera.cameraRot = new Vector3d(90, 0, 0);
    }

    private static void move(final float distance) {
        Camera.cameraTrans = new Vector3d(Camera.cameraTrans.get(0),
                Camera.cameraTrans.get(1), Camera.cameraTrans.get(2) + distance);
    }

}